#include "ch32x035.h"
#include "stdio.h"
#include "stdint.h"
#include "string.h"
#include "microConfig.h"
#include "DevicesTime.h"
#include "DevicesDelay.h"
#include "DevicesQueue.h"
#include "DriverPD.h"


/* USB PD DMA 需要4字节对齐 */
__attribute__ ((aligned(4))) PdMessStdType g_typePDMessTx, g_typePDMessRx;

/* PD接口 */
PdType g_typePD = {.version = 2, .extended = 1};

const PdCapabiType g_typeSrcCapabi[] =
{
    {.fixed = {.type = 0, .voltage = 5000  / 50, .maxCurrent = 3000 / 10, .dualRolePower = 0, .dualRoleData = 0, .EprMode = 1, .UEMS = 1}},
    {.fixed = {.type = 0, .voltage = 9000  / 50, .maxCurrent = 3000 / 10}},
    {.fixed = {.type = 0, .voltage = 15000 / 50, .maxCurrent = 3000 / 10}},
    {.fixed = {.type = 0, .voltage = 20000 / 50, .maxCurrent = 5000 / 10}},
    {.fixed = {.type = 0, .voltage = 28000 / 50, .maxCurrent = 5000 / 10}},
    {.fixed = {.type = 0, .voltage = 48000 / 50, .maxCurrent = 5000 / 10}},
    {.sprProgram = {.type = 3, .APDO = 0, .maxVoltage = 20000 / 100, .minVoltage = 3300 / 100, .maxCurrent = 5000 / 50}},
};

const PdCapabiType g_typeSinkCapabi[] =
{
    {.sinkFixed = {.type = 0, .voltage = 5000  / 50, .maxCurrent = 3000 / 10, .dualRolePower = 0, .dualRoleData = 0, .fastRoleSwap = 0}},
    {.sinkFixed = {.type = 0, .voltage = 9000  / 50, .maxCurrent = 3000 / 10}},
    {.sinkFixed = {.type = 0, .voltage = 15000 / 50, .maxCurrent = 3000 / 10}},
    {.sinkFixed = {.type = 0, .voltage = 20000 / 50, .maxCurrent = 5000 / 10}},
};

const PdVdmHeadType g_typePdVdmHead =
{
    .VID = 0xFF00,
    .type = 1,
    .majorVersion = 1,
    .minorVersion = 0,
    .objectPosition = 0,
    .commandType = 0,
    .reserved1 = 0,
    .command = 1,
};


/* ms */
uint32_t uiPdTimeGet(void)
{
    return lTimebaseGet() / 1000LL;
}

void USBPD_IRQHandler(void) __attribute__((interrupt()));
void USBPD_IRQHandler(void)
{
    vMrStackSwitchToSystem();

    /* 接收完成中断标志 */
    if(USBPD->STATUS & IF_RX_ACT)
    {
        /* 清除接收完成中断标志 */
        USBPD->STATUS |= IF_RX_ACT;

        /* 协议规定，数据长度为：2 - 30 Byte */
        if(USBPD->BMC_BYTE_CNT > 1)
        {
            /* 如果不是接收到GoodCRC，则需要处理数据，以及回复GoodCRC */
            if(!((g_typePDMessRx.head.type == DEF_TYPE_GOODCRC) && (g_typePDMessRx.head.number == 0)))
            {
                /* SOP0 是与设备通信 */
                if((USBPD->STATUS & MASK_PD_STAT) == PD_RX_SOP0)
                {
                    enumQueuePushDatas(&g_TypeQueueUsbPdRead, &g_typePDMessRx, sizeof(PdMessHeadType) + g_typePDMessRx.head.number * 4);

                    /* 及时回复 GoodCRC */
                    cPdPackControlSend(UPD_SOP0, DEF_TYPE_GOODCRC, g_typePDMessRx.head.ID);
                }
                /* SOP' 和 SOP'' 是src与线材通信 */
                else if(((USBPD->STATUS & MASK_PD_STAT) == PD_RX_SOP1_HRST) && (g_typePD.PortPowerRole == 1) && (g_typePDMessRx.head.PortPowerRole == 1))
                {
                    enumQueuePushDatas(&g_TypeQueueUsbPdRead, &g_typePDMessRx, sizeof(PdMessHeadType) + g_typePDMessRx.head.number * 4);

                    /* 及时回复 GoodCRC */
                    cPdPackControlSend(UPD_SOP1, DEF_TYPE_GOODCRC, g_typePDMessRx.head.ID);
                }
            }
        }
    }

    /* 接收复位中断标志 */
    if(USBPD->STATUS & IF_RX_RESET)
    {
        /* 清除复位中断标志 */
        USBPD->STATUS |= IF_RX_RESET;

        cPdResetHard();
    }

    /* 发送完成中断标志 */
    if(USBPD->STATUS & IF_TX_END)
    {
        /* 清除发送完成中断标志  */
        USBPD->STATUS |= IF_TX_END;

        cPdRxMode();
    }

    vMrStackSwitchToTask();
}

int8_t cPdInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    NVIC_InitTypeDef NVIC_InitStructure = {0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBPD, ENABLE);

    GPIO_InitStructure.GPIO_Pin = PIN_CC1 | PIN_CC2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    /* 测试使用，检测此引脚的输入电平，低电平是SINK，高电平是SRC */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    /* 配置 USB PD CC 引脚模式 */
    AFIO->CTLR |= USBPD_IN_HVT | USBPD_PHY_V33;

    /* 设置 CC线 以正常VDD电压驱动输出 */
    USBPD->PORT_CC1 &= ~CC_LVE;
    USBPD->PORT_CC2 &= ~CC_LVE;

    /* 清除全部状态 */
    USBPD->STATUS = BUF_ERR | IF_RX_BIT | IF_RX_BYTE | IF_RX_ACT | IF_RX_RESET | IF_TX_END;

    /* 开启发送完成中断、接收完成中断、接收复位中断 */
    USBPD->CONFIG = IE_TX_END | IE_RX_ACT | IE_RX_RESET | PD_DMA_EN;

    cPdResetHard();

    NVIC_InitStructure.NVIC_IRQChannel = USBPD_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    return 0;
}

int8_t cPdResetHard(void)
{
    GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3) ? cPdSrcInit() : cPdSinkInit();

    cPdRxMode();

    g_typePD.connected = 0;

    return 0;
}

int8_t cPdResetSoft(void)
{
    g_typePDMessTx.head.ID = 0;

    return 0;
}

int8_t cPdSrcInit(void)
{
    /* 设置 USB_VBUS 的驱动能力为3A，后续通过协议握手会更改为真实的驱动能力 */
    USBPD->PORT_CC1 = CC_CMP_66 | CC_PU_330;
    USBPD->PORT_CC2 = CC_CMP_66 | CC_PU_330;

    g_typePD.PortPowerRole = 1;
    g_typePD.PortDataRole = 1;

    return 0;
}

int8_t cPdSinkInit(void)
{
    USBPD->PORT_CC1 = CC_CMP_66 | CC_PD;
    USBPD->PORT_CC2 = CC_CMP_66 | CC_PD;

    g_typePD.PortPowerRole = 0;
    g_typePD.PortDataRole = 0;

    return 0;
}

/* 配置 CC 通道 */
void vPdCCSet(uint8_t ucFlags)
{
    /* 选择对应的 CC 端口通讯 */
    (ucFlags & 0x20) ? (USBPD->CONFIG |= CC_SEL) : (USBPD->CONFIG &= ~CC_SEL);

    printf("%s connected.\r\n", (USBPD->PORT_CC1 & CC_PD) ? "SINK" : "SRC");

    g_typePD.connected  = (ucFlags & 0x0F) ? 0x01 : 0x00;
    g_typePD.connected |= (ucFlags & 0xF0) ? 0x02 : 0x00;

    /* 等待源端发送 电源参数 列表 */
    g_typePD.timeout = uiPdTimeGet();
    g_typePD.status = STA_SRC_CONNECT;
}

uint8_t ucPdCCDetect(void)
{
    static uint8_t st_ucFlagLast = 0;
    uint32_t uiFlags[6] = {0}, uiMask;
    uint8_t ucFlag = 0;

    /* 检测 CC 引脚状态 */
    {
        USBPD->PORT_CC1 = (USBPD->PORT_CC1 & ~(CC_CMP_Mask | PA_CC_AI)) | CC_CMP_22;
        USBPD->PORT_CC2 = (USBPD->PORT_CC2 & ~(CC_CMP_Mask | PA_CC_AI)) | CC_CMP_22;
        for(uiMask = 1; uiMask; uiMask <<= 1)
        {
            /* 检测 CC1、CC2 电压是否是高电平 */
            uiFlags[2] |= (GPIOC->INDR & PIN_CC1)      ? uiMask : 0;
            uiFlags[5] |= (GPIOC->INDR & PIN_CC2)      ? uiMask : 0;

            /* 检测 CC1、CC2 电压是否超过0.22V */
            uiFlags[0] |= (USBPD->PORT_CC1 & PA_CC_AI) ? uiMask : 0;
            uiFlags[3] |= (USBPD->PORT_CC2 & PA_CC_AI) ? uiMask : 0;
            USBPD->PORT_CC1 &= ~PA_CC_AI;
            USBPD->PORT_CC2 &= ~PA_CC_AI;
        }

        USBPD->PORT_CC1 = (USBPD->PORT_CC1 & ~(CC_CMP_Mask | PA_CC_AI)) | CC_CMP_66;
        USBPD->PORT_CC2 = (USBPD->PORT_CC2 & ~(CC_CMP_Mask | PA_CC_AI)) | CC_CMP_66;
        for(uiMask = 1; uiMask; uiMask <<= 1)
        {
            /* 检测 CC1、CC2 电压是否超过0.66V */
            uiFlags[1] |= (USBPD->PORT_CC1 & PA_CC_AI) ? uiMask : 0;
            uiFlags[4] |= (USBPD->PORT_CC2 & PA_CC_AI) ? uiMask : 0;
            USBPD->PORT_CC1 &= ~PA_CC_AI;
            USBPD->PORT_CC2 &= ~PA_CC_AI;
        }

        ucFlag |= (uiFlags[0] == 0xFFFFFFFF) ? 0x01 : ((uiFlags[0] == 0x00000000) ? 0 : 0x08);
        ucFlag |= (uiFlags[1] == 0xFFFFFFFF) ? 0x02 : ((uiFlags[1] == 0x00000000) ? 0 : 0x08);
        ucFlag |= (uiFlags[2] == 0xFFFFFFFF) ? 0x04 : ((uiFlags[2] == 0x00000000) ? 0 : 0x08);
        ucFlag |= (uiFlags[3] == 0xFFFFFFFF) ? 0x10 : ((uiFlags[3] == 0x00000000) ? 0 : 0x80);
        ucFlag |= (uiFlags[4] == 0xFFFFFFFF) ? 0x20 : ((uiFlags[4] == 0x00000000) ? 0 : 0x80);
        ucFlag |= (uiFlags[5] == 0xFFFFFFFF) ? 0x40 : ((uiFlags[5] == 0x00000000) ? 0 : 0x80);
    }

    /* 有抖动 */
    if(ucFlag & 0x88)
    {
        // printf("CC%d 有抖动 %08X, %08X, %08X, %08X, %08X, %08X\r\n", (ucFlag & 0x08) ? 1 : 2, uiFlags[0], uiFlags[1], uiFlags[2], uiFlags[3], uiFlags[4], uiFlags[5]);
        return st_ucFlagLast;
    }

    if((ucFlag == st_ucFlagLast) && (g_typePD.connected != 0))
        return st_ucFlagLast;

    printf("ucPdCCDetect now: 0x%02X, last: 0x%02X\r\n", ucFlag, st_ucFlagLast);

    st_ucFlagLast = ucFlag;

    /* 配置 CC 通道 */
    vPdCCSet(ucFlag);

    return ucFlag;
}

int8_t cPdRxMode(void)
{
    /* 清除全部状态 */
    USBPD->CONFIG  |=  PD_ALL_CLR;
    USBPD->CONFIG  &= ~PD_ALL_CLR;

    USBPD->BMC_CLK_CNT = UPD_TMR_RX_48M;
    USBPD->DMA      = (uint32_t)&g_typePDMessRx;
    /* 设置为接收模式 */
    USBPD->CONTROL &= ~PD_TX_EN;
    /* 开始接收 */
    USBPD->CONTROL |= BMC_START;

    return 0;
}

static int8_t cPdDatasSend(uint8_t ucSop, void *pvDatas, int32_t iLength)
{
    /* 只有当发送指针为NULL，但发送长度又不为0时，才是错误状态 */
    if((pvDatas == NULL) && (iLength > 0))
        return 1;

//    uint8_t *pucDatas = pvDatas;
//    int32_t i = 0;

//    printf("cPdDatasSend %d: ", ucSop);
//    for(i = 0; i < iLength; ++i)
//    {
//        printf(" %02X", *pucDatas++);
//    }
//    printf("\r\n");

    USBPD->BMC_CLK_CNT  = UPD_TMR_TX_48M;
    USBPD->TX_SEL       = ucSop;
    USBPD->DMA          = (uint32_t)pvDatas;
    USBPD->BMC_TX_SZ    = iLength;

    /* 清除发送完成状态 */
    USBPD->STATUS      |= IF_TX_END;
    /* 发送使能 */
    USBPD->CONTROL     |= PD_TX_EN;
    /* 开始发送 */
    USBPD->CONTROL     |= BMC_START;

    /* 等待发送完成 （发送完成中断，会设置为接收模式）*/
    while(((USBPD->STATUS & IF_TX_END) == 0) && (USBPD->CONTROL & PD_TX_EN));

    return 0;
}

int8_t cPdMessHeadLoad(void *pvHead, uint8_t ucSop, uint8_t ucEx, uint8_t ucType, uint8_t ucID, uint8_t ucLength)
{
    PdMessHeadType *ptypeMessHead = (PdMessHeadType *)pvHead;

    if(pvHead == NULL)
        return 1;

    ptypeMessHead->extended         = ucEx;
    ptypeMessHead->number           = ucLength >> 2;
    ptypeMessHead->ID               = ucID;
    ptypeMessHead->PortPowerRole    = (ucSop == UPD_SOP0) ? g_typePD.PortPowerRole : 0;
    ptypeMessHead->version          = g_typePD.version;
    ptypeMessHead->PortDataRole     = (ucSop == UPD_SOP0) ? g_typePD.PortDataRole : 0;
    ptypeMessHead->type             = ucType;

    return 0;
}

int8_t cPdMessExHeadLoad(void *pvHead, uint8_t ucChunked, uint8_t ucChunkNumber, uint8_t ucRequestChunk, uint8_t ucDataSize)
{
    PdMessExHeadType *ptypeMessExHead = (PdMessExHeadType *)pvHead;

    if(pvHead == NULL)
        return 1;

    ptypeMessExHead->chunked        = ucChunked;
    ptypeMessExHead->chunkNumber    = ucChunkNumber;
    ptypeMessExHead->requestChunk   = ucRequestChunk;
    ptypeMessExHead->dataSize       = ucDataSize;

    return 0;
}

/* 利用CC发送一帧数据 */
int8_t cPdPackSend(uint8_t ucSop, uint8_t ucEx, uint8_t ucType, uint8_t ucID, void *pvDatas, int32_t iDataLength, int8_t cWaitCnt)
{
    PdMessStdType *ptypePdMess = &g_typePDMessTx;
    int8_t cTimeout;

    /* 加载消息头 */
    cPdMessHeadLoad(&ptypePdMess->head, ucSop, ucEx, ucType, ucID, iDataLength);

    /* 加载消息数据 */
    memcpy(ptypePdMess->datas, pvDatas, iDataLength);

    /* 协议规定最多发送 3 次，直到收到 GoodCRC */
    do
    {
        g_typePDMessRx.head.type = 0;

        /* 发送消息 */
        cPdDatasSend(ucSop, ptypePdMess, 2 + iDataLength);

        /* 协议规定等待超时（0.9~1.1ms) */
        for(cTimeout = 100; (g_typePDMessRx.head.type != DEF_TYPE_GOODCRC) && cWaitCnt && cTimeout; --cTimeout)
        {
            vDelayUs(10);
        }
    }
    while(((--cWaitCnt) > 0) && (cTimeout <= 0));

    return (cTimeout == 0);
}

/* 利用CC发送一帧拓展数据 */
int8_t cPdPackExSend(uint8_t ucSop, uint8_t ucType, uint8_t ucID, uint8_t ucChunked, uint8_t ucChunkNumber, uint8_t ucRequestChunk, void *pvDatas, int32_t iDataLength, int8_t cWaitCnt)
{
    PdMessStdType *ptypePdMess = &g_typePDMessTx;
    int16_t sTimeout;

    /* 加载拓展消息头 */
    cPdMessExHeadLoad(&ptypePdMess->headEx, ucChunked, ucChunkNumber, ucRequestChunk, iDataLength);

    /* 加载消息数据 */
    memcpy(&ptypePdMess->datas[2], pvDatas, iDataLength);

    /* 长度补齐到4字节 */
    iDataLength = (ucChunked == 0) ? iDataLength + 2 : PD_ROUND_UP(iDataLength + 2, 4);

    /* 加载消息头 */
    cPdMessHeadLoad(&ptypePdMess->head, ucSop, 1, ucType, ucID, (ucChunked == 0) ? 0 : iDataLength);

    /* 协议规定最多发送 3 次，直到收到 GoodCRC */
    do
    {
        g_typePDMessRx.head.type = 0;

        /* 发送消息 */
        cPdDatasSend(ucSop, ptypePdMess, 2 + iDataLength);

        /* 协议规定等待超时（0.9~1.1ms) */
        for(sTimeout = 1000; (g_typePDMessRx.head.type != DEF_TYPE_GOODCRC) && cWaitCnt && sTimeout; --sTimeout)
        {
            vDelayUs(10);
        }
    }
    while(((--cWaitCnt) > 0) && (sTimeout <= 0));

    return (sTimeout == 0);
}

/* 请求第x个电源 */
int8_t cPdRequest(uint8_t ucIndex)
{
    PdRequestCapabiType typeRequestCapabi = {0};

    typeRequestCapabi.UEMS              = g_typePD.extended;
    typeRequestCapabi.objectPosition    = ucIndex + 1;
    /* 请求需要的电流大小 */
    typeRequestCapabi.operatCurrent     = g_typePD.srcCapabi[ucIndex].fixed.maxCurrent;
    typeRequestCapabi.maxCurrent        = g_typePD.srcCapabi[ucIndex].fixed.maxCurrent;

    return cPdPackDatasSend(UPD_SOP0, DEF_TYPE_REQUEST, g_typePDMessTx.head.ID++, &typeRequestCapabi, sizeof(typeRequestCapabi));
}

int8_t cPdCapabilitesDecode(PdType *ptypePd)
{
    uint32_t voltageMax, voltageMin, currentMax, powerMax;
    uint8_t i;

    for(i = 0; i < ptypePd->srcCapabNum; ++i)
    {
        if(ptypePd->srcCapabi[i].fixed.type == 0)
        {
            voltageMin = ptypePd->srcCapabi[i].fixed.voltage * 50;
            currentMax = ptypePd->srcCapabi[i].fixed.maxCurrent * 10;

            printf("PDO %d fixed voltage: %d \t currentMax: %d\r\n", i, voltageMin, currentMax);
        }
        else if(ptypePd->srcCapabi[i].fixed.type == 1)
        {
            voltageMax = ptypePd->srcCapabi[i].battery.maxVoltage * 50;
            voltageMin = ptypePd->srcCapabi[i].battery.minVoltage * 50;
            powerMax   = ptypePd->srcCapabi[i].battery.maxPower * 250;

            printf("PDO %d battery voltageMax: %d \t voltageMin: %d \t powerMax: %d\r\n", i, voltageMax, voltageMin, powerMax);
        }
        else if(ptypePd->srcCapabi[i].fixed.type == 2)
        {
            voltageMax = ptypePd->srcCapabi[i].variable.maxVoltage * 50;
            voltageMin = ptypePd->srcCapabi[i].variable.minVoltage * 50;
            currentMax = ptypePd->srcCapabi[i].variable.maxCurrent * 10;

            printf("PDO %d variable voltageMax: %d \t voltageMin: %d \t currentMax: %d\r\n", i, voltageMax, voltageMin, currentMax);
        }
        else if(ptypePd->srcCapabi[i].sprProgram.APDO == 0)
        {
            voltageMax = ptypePd->srcCapabi[i].sprProgram.maxVoltage * 100;
            voltageMin = ptypePd->srcCapabi[i].sprProgram.minVoltage * 100;
            currentMax = ptypePd->srcCapabi[i].sprProgram.maxCurrent * 50;

            printf("PDO %d Program voltageMax: %d \t voltageMin: %d \t currentMax: %d\r\n", i, voltageMax, voltageMin, currentMax);
        }
        else if(ptypePd->srcCapabi[i].sprProgram.APDO == 1)
        {
            voltageMax = ptypePd->srcCapabi[i].eprAdjus.maxVoltage * 100;
            voltageMin = ptypePd->srcCapabi[i].eprAdjus.minVoltage * 100;
            powerMax   = ptypePd->srcCapabi[i].eprAdjus.inctements * 50;

            printf("PDO %d EPR voltageMax: %d \t voltageMin: %d \t powerMax: %d\r\n", i, voltageMax, voltageMin, powerMax);
        }
        else if(ptypePd->srcCapabi[i].sprProgram.APDO == 2)
        {
            printf("PDO %d SPR\r\n", i);
        }
        else
        {
            printf("SPR error.\r\n");
        }
    }

    return 0;
}

int8_t cPdPassiveCableDecode(PdType *ptypePd)
{
    static char *st_cVoltage[4] = {"20V", "30V", "40V", "50V"};
    static char *st_cCurrents[4] = {"Reserved", "3A", "5A", "Reserved"};
    static char *st_cSpeeds[8] = {"USB 2.0", "USB 3.2 Gen1", "USB 3.2 Gen2", "USB4 Gen3", "USB4 Gen4", "Reserved", "Reserved", "Reserved"};

    printf("\n\rPassiveCable:\r\n");
    printf("version hard: %X, ", ptypePd->passiveCable.hardVersion);
    printf("soft: %X, ",         ptypePd->passiveCable.softVersion);
    printf("VDO: %d\r\n",        ptypePd->passiveCable.vdoVersion);

    printf("cableLatency: %dm, ", ptypePd->passiveCable.cableLatency);
    printf("voltage: %s, ",       st_cVoltage[ptypePd->passiveCable.maxVoltage]);
    printf("currentCapab: %s, ",  st_cCurrents[ptypePd->passiveCable.currentCapab]);
    printf("speed: %s\r\n",       st_cSpeeds[ptypePd->passiveCable.speed]);

    return 0;
}

int8_t cPdMessRecive(PdMessStdType *ptypePdMess)
{
    PdType *ptypePd = &g_typePD;

    if(ptypePdMess == NULL)
        return 1;

//    int8_t i;
//    printf("cPdMessRecive:\r\n");
//    printf("head: %d, %d, %d, %d, %d, %d, %d\r\n",
//             ptypePdMess->head.extended,
//             ptypePdMess->head.number,
//             ptypePdMess->head.ID,
//             ptypePdMess->head.PortPowerRole,
//             ptypePdMess->head.version,
//             ptypePdMess->head.PortDataRole,
//             ptypePdMess->head.type);
//    printf("data:");
//    for(i = 0; i < ptypePdMess->head.number; ++i)
//    {
//        printf(" %08X", ptypePdMess->datas[i]);
//    }
//    printf("\r\n");

    /* 非拓展消息 */
    if(ptypePdMess->head.extended == 0)
    {
        /* 控制消息 */
        if(ptypePdMess->head.number == 0)
        {
            switch(ptypePdMess->head.type)
            {
                /* GotoMin消息只适用于那些在接收请求数据对象。它是对接收端口的一个指令，将其操作功率级别降低到最小. */
                case DEF_TYPE_GOTOMIN:
                    printf("DEF_TYPE_GOTOMIN\r\n");
                    break;

                /* 在这些情况下，接受讯息是有效的回应: Request、PR_Swap、DR_Swap、VCONN_Swap、FR_Swap、Soft_Reset */
                case DEF_TYPE_ACCEPT:
                    printf("DEF_TYPE_ACCEPT\r\n");
                    ptypePd->timeout = uiPdTimeGet();
                    ptypePd->status = (ptypePd->status == STA_RX_ACCEPT_WAIT) ? STA_RX_PS_RDY_WAIT : STA_IDLE;
                    break;

                    /* 在这些情况下，接受讯息是有效的回应: Request、PR_Swap、DR_Swap、VCONN_Swap */
                case DEF_TYPE_REJECT:
                    printf("DEF_TYPE_REJECT\r\n");
                    break;

                    /* 由源发送表示电源已达到所需的工作状态 */
                case DEF_TYPE_PS_RDY:
                    printf("DEF_TYPE_PS_RDY\r\n");
                    ptypePd->status = STA_IDLE;
                    break;

                    /* 得到源端功能，对方回应Source_Capabilities Message */
                case DEF_TYPE_GET_SRC_CAP:
                    printf("DEF_TYPE_GET_SRC_CAP\r\n");
                    cPdPackDatasSend(UPD_SOP0, DEF_TYPE_SRC_CAP, g_typePDMessTx.head.ID++, (void *)&g_typeSrcCapabi, sizeof(g_typeSrcCapabi));
                    break;

                    /* 得到Sink端功能，对方回应Sink_Capabilities Message */
                case DEF_TYPE_GET_SNK_CAP:
                    printf("DEF_TYPE_GET_SNK_CAP\r\n");
                    cPdPackDatasSend(UPD_SOP0, DEF_TYPE_SNK_CAP, g_typePDMessTx.head.ID++, (void *)&g_typeSinkCapabi, sizeof(g_typeSinkCapabi));
                    break;

                    /* DR_Swap消息的接收者应通过发送Accept消息、Reject消息或Wait消息来响应。接收到Accept后，DFP，UFP交换角色。Reject不采取措施。Wait表示将来可能交换，暂时不采取操作 */
                case DEF_TYPE_DR_SWAP:
                    printf("DEF_TYPE_DR_SWAP\r\n");
                    cPdPackControlSend(UPD_SOP0, DEF_TYPE_REJECT, g_typePDMessTx.head.ID++);
                    break;

                    /* 任何端口合作伙伴都可以发送PR_Swap消息来请求交换电源角色。返回消息为Accept消息、Reject消息或Wait */
                case DEF_TYPE_PR_SWAP:
                    printf("DEF_TYPE_PR_SWAP\r\n");
                    cPdPackControlSend(UPD_SOP0, DEF_TYPE_REJECT, g_typePDMessTx.head.ID++);
                    break;

                    /* 交换VCONN角色。消息发送后，对方执行。新的V CONN源将发送PS_RDY消息，指示它现在正在寻找VCONN。初始V CONN源在收到PS_RDY消息的最后一位EOP后，应停止在tVCONNSourceOff内寻找VCONN */
                case DEF_TYPE_VCONN_SWAP:
                    printf("DEF_TYPE_VCONN_SWAP\r\n");
                    cPdPackControlSend(UPD_SOP0, DEF_TYPE_REJECT, g_typePDMessTx.head.ID++);
                    break;

                    /* 回复对方的请求，让对方稍等再进行请求 */
                case DEF_TYPE_WAIT:
                    printf("DEF_TYPE_WAIT\r\n");
                    break;

                /* 当存在消息同步错误时，源或接收器可以发送一条Soft_Reset消息。软t_reset消息从协议层错误中恢复。接收放会恢复到PE_SNK_Ready和PE_SRC_Ready状态 */
                case DEF_TYPE_SOFT_RESET:
                    printf("DEF_TYPE_SOFT_RESET\r\n");
                    cPdResetSoft();
                    cPdPackControlSend(UPD_SOP0, DEF_TYPE_ACCEPT, g_typePDMessTx.head.ID++);
                    break;

                    /* 数据复位 */
                case DEF_TYPE_DATA_RESET:
                    printf("DEF_TYPE_DATA_RESET\r\n");
                    break;

                    /* 数据复位完成 */
                case DEF_TYPE_DATA_RESET_CMP:
                    printf("DEF_TYPE_DATA_RESET_CMP\r\n");
                    break;

                    /* 不支持对方发送的请求 */
                case DEF_TYPE_NOT_SUPPORT:
                    printf("DEF_TYPE_NOT_SUPPORT\r\n");
                    break;

                    /* 请求关于端口源功能的附加信息 */
                case DEF_TYPE_GET_SRC_CAP_EX:
                    printf("DEF_TYPE_GET_SRC_CAP_EX\r\n");
                    break;

                    /* 请求端口合作伙伴的当前状态。源或接收器应返回一条状态消息作为响应 */
                case DEF_TYPE_GET_STATUS:
                    printf("DEF_TYPE_GET_STATUS\r\n");
                    break;

                    /* 接收器发送Get_PPS_Status消息来请求关于源状态的附加信息 */
                case DEF_TYPE_GET_PPS_STATUS:
                    printf("DEF_TYPE_GET_PPS_STATUS\r\n");
                    break;

                    /* 支持的[ISO 3166]中定义的alpha-2国家代码 */
                case DEF_TYPE_GET_CTY_CODES:
                    printf("DEF_TYPE_GET_CTY_CODES\r\n");
                    break;

                default : break;
            }
        }
        /* 数据消息 */
        else
        {
            switch(ptypePdMess->head.type)
            {
                /* 供电方的供电能力信息 */
                case DEF_TYPE_SRC_CAP:
                    printf("DEF_TYPE_SRC_CAP\r\n");
                    memcpy(ptypePd->srcCapabi, ptypePdMess->datas, ptypePdMess->head.number * 4);
                    ptypePd->srcCapabNum = ptypePdMess->head.number;

                    /* 解析接收到的 电源端 列表 */
                    cPdCapabilitesDecode(ptypePd);

                    ptypePd->status = STA_TX_REQ;
                    break;

                case DEF_TYPE_REQUEST:
                    printf("DEF_TYPE_REQUEST\r\n");
                    cPdPackControlSend(UPD_SOP0, DEF_TYPE_ACCEPT, g_typePDMessTx.head.ID++);
                    ptypePd->status = STA_TX_PS_RDY;
                    break;

                    /* 线缆的数据 */
                case DEF_TYPE_VENDOR_DEFINED:
                    printf("DEF_TYPE_VENDOR_DEFINED\r\n");
                    memcpy(&ptypePd->passiveCable, &ptypePdMess->datas[16], sizeof(ptypePd->passiveCable));

                    /* 解析接收到的线缆数据 */
                    cPdPassiveCableDecode(ptypePd);
                    break;

                default : break;
            }
        }
    }
    /* 拓展消息 */
    else
    {

    }

    return 0;
}

int8_t cPdPoll(void)
{
    PdType *ptypePd = &g_typePD;
    PdMessStdType typePDMess;
    int8_t cError = 0;

    /* 空闲、并超时时，才检测CC引脚状态 */
    if(((ptypePd->status == STA_IDLE) && (uiPdTimeGet() - ptypePd->timeout) > 100))
    {
        /* 检测CC引脚 */
        ucPdCCDetect();
    }

    /* 读取并解析 USB CC 发送过来的数据 */
    while((enumQueuePopDatas(&g_TypeQueueUsbPdRead, &typePDMess.head,  sizeof(PdMessHeadType))     == queueNormal) &&
          (enumQueuePopDatas(&g_TypeQueueUsbPdRead, &typePDMess.datas, typePDMess.head.number * 4) == queueNormal))
    {
        cPdMessRecive(&typePDMess);
    }

    /* 执行状态机 */
    switch(ptypePd->status)
    {
        case STA_IDLE :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_IDLE\r\n") : (void)0;
            break;

        case STA_SRC_CONNECT :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_SRC_CONNECT\r\n") : (void)0;
            ptypePd->timeout = uiPdTimeGet();
            ptypePd->status = (USBPD->PORT_CC1 & CC_PD) ? STA_RX_SRC_CAP_WAIT : STA_TX_REQ_CABLE;
            break;

        case STA_RX_SRC_CAP_WAIT :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_RX_SRC_CAP_WAIT\r\n") : (void)0;
            if((uiPdTimeGet() - ptypePd->timeout) > 3000)
                ptypePd->status = STA_TX_HRST;
            break;

        case STA_TX_REQ :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_TX_REQ\r\n") : (void)0;
            /* 请求第x个电源 */
            cError = cPdRequest(0);
            ptypePd->timeout = uiPdTimeGet();
            ptypePd->status  = (cError == 0) ? STA_RX_ACCEPT_WAIT : STA_IDLE;
            break;

        case STA_RX_ACCEPT_WAIT :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_RX_ACCEPT_WAIT\r\n") : (void)0;
            if((uiPdTimeGet() - ptypePd->timeout) > 3000)
                ptypePd->status = STA_TX_HRST;
            break;

        case STA_RX_PS_RDY_WAIT :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_RX_PS_RDY_WAIT\r\n") : (void)0;
            if((uiPdTimeGet() - ptypePd->timeout) > 3000)
                ptypePd->status = STA_TX_HRST;
            break;

        case STA_RX_REQ_WAIT :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_RX_REQ_WAIT\r\n") : (void)0;
            if((uiPdTimeGet() - ptypePd->timeout) > 3000)
                ptypePd->status = STA_TX_HRST;
            break;

        case STA_TX_REQ_CABLE :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_TX_REQ_CABLE\r\n") : (void)0;
            cError = cPdPackDatasSend(UPD_SOP1, DEF_TYPE_VENDOR_DEFINED, g_typePDMessTx.head.ID++, (void *)&g_typePdVdmHead, sizeof(g_typePdVdmHead));
            ptypePd->status = STA_TX_SRC_CAP;
            break;

        case STA_TX_SRC_CAP :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_TX_SRC_CAP\r\n") : (void)0;
            /* 超时重复发送 */
            if((uiPdTimeGet() - ptypePd->timeout) < 100)
                break;
            ptypePd->timeout = uiPdTimeGet();

            cError = cPdPackDatasSend(UPD_SOP0, DEF_TYPE_SRC_CAP, g_typePDMessTx.head.ID++, (void *)&g_typeSrcCapabi, sizeof(g_typeSrcCapabi));
            ptypePd->status = (cError == 0) ? STA_IDLE : STA_TX_SRC_CAP;
            break;

        case STA_TX_ACCEPT :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_TX_ACCEPT\r\n") : (void)0;
            cError = cPdPackControlSend(UPD_SOP0, DEF_TYPE_ACCEPT, g_typePDMessTx.head.ID++);
            ptypePd->status = STA_IDLE;
            break;

        case STA_TX_REJECT :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_TX_REJECT\r\n") : (void)0;
            cError = cPdPackControlSend(UPD_SOP0, DEF_TYPE_REJECT, g_typePDMessTx.head.ID++);
            ptypePd->status = STA_IDLE;
            break;

        case STA_TX_PS_RDY :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_TX_PS_RDY\r\n") : (void)0;
            cError = cPdPackControlSend(UPD_SOP0, DEF_TYPE_PS_RDY, g_typePDMessTx.head.ID++);
            ptypePd->status = STA_IDLE;
            break;

        case STA_TX_SOFTRST :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_TX_SOFTRST\r\n") : (void)0;
            cError = cPdPackControlSend(UPD_SOP0, DEF_TYPE_SOFT_RESET, g_typePDMessTx.head.ID++);
            ptypePd->status = STA_IDLE;
            break;

        case STA_TX_HRST :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_TX_HRST\r\n") : (void)0;
            cError = cPdDatasSend(UPD_HARD_RESET, NULL, 0);
            ptypePd->timeout = uiPdTimeGet();
            ptypePd->status = (USBPD->PORT_CC1 & CC_PD) ? STA_RX_SRC_CAP_WAIT : STA_TX_SRC_CAP;
            break;

        default : cError = 1; break;
    }

    return cError;
}
